package zhuzx.solution;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SplitUtil {
	
	/**
	 * 【空格|制表符|换行符|中英文右括号|中英文分号|中英文句号 + 选项标号 + 顿号|空格|英文句号】
	 * \s表示包括上述三种在内的所有空白符
	 */
	public static final String REGEX = "[\\s)）;；.。][A-J][、. ]";
	public static final String REGEX_LINE = "[\\n][A-J][、. ]";
	public static final String REGEX_HALF = "[A-J][、. ]";
	public static final Pattern PATTERN = Pattern.compile(REGEX);
	public static final Pattern PATTERN_HALF = Pattern.compile(REGEX_HALF);
	public static final int A = (int) 'A';

	/**
	 * 优先按换行符分割，不满足则再按标号左右匹配字符分割，还不满足则按标号右边匹配字符分割。<br>
	 * 若存在无法在程序中分割选项的情况，则返回原字符串给调用者处理，通过返回数组的长度判断。
	 * @param sourceStr 需要分割的字符串
	 * @return 返回分割得到的结果数组，若数组长度为1，则表示无法分割，需要额外处理
	 */
	public static String[] splitOptions(String sourceStr) {
		String[] options = sourceStr.split(REGEX_LINE);
		//纯换行符分割，可以保证无误，直接返回
		if (options.length >= 5) {
			return options;
		}
		options = sourceStr.split(REGEX);
		//选项之间是否存在无间隔的情况
		boolean isContinuous = options.length < 5;
		if (isContinuous) {
			options = sourceStr.split(REGEX_HALF);
		}
		//超过四个选项或者选项内容中匹配到标号
		if (options.length > 5) {
			Pattern p = isContinuous ? PATTERN_HALF : PATTERN;
			Matcher m = p.matcher(sourceStr);
			String optionMark = null;
			boolean isFindA = false;
			//用来保存合并子串之后的结果
			String[] affixed = new String[options.length];
			//实际的题目+选项数量，用来作为affixed数组的索引
			int indexNew = 0;
			int indexOld = -1;
			boolean isPerfectIncrease = true;
			boolean findInTitle = false;
			while (m.find()) {
				indexOld++;
				optionMark = m.group();
				//得到标号，即ABCD的单个字符
				char c = isContinuous ? optionMark.charAt(0) : optionMark.charAt(1);
				if (!isFindA) {//处理在题目中而不是选项中就匹配到标号的情况
					if (c == 'A') {
						isFindA = true;
						indexNew++;
					} else {
						//全部放在affixed[0]里面
						affixed[indexNew] = options[indexOld] + optionMark + options[indexOld+1];
						findInTitle = true;
						//因为把options的下一个数组元素也合并掉了，所以要额外+1
						indexOld++;
						continue;
					}
				}
				//根据标号的ASCII码值判断是否按字母表连续递增
				int ascii = (int) c;
				System.out.print(c);
				if (ascii == (A + indexNew - 1)) {//若匹配到的选项标号是按序递增，则继续循环，否则indexNew不增加
					if (findInTitle) {
						affixed[indexNew] = options[indexOld];
					}
					indexNew++;
				} else if (ascii == (A + indexNew - 2)) {//连续匹配到了相同的标号，如选项B的内容中中存在【B、】
					//暂时人工区分
					return new String[] {sourceStr};
				} else {//匹配到的结果可以确定不是正常的标号，比如B选项中出现了【A、】或者【C、】，可以合并到前面的选项中去
					affixed[indexNew-1] = affixed[indexNew-1] + optionMark + options[indexOld];
					isPerfectIncrease = false;
				}
			}
			if (findInTitle || !isPerfectIncrease) {
				//标题中出现匹配结果或者不是完美递增，把合并后的结果复制到合适大小的数组
				options = new String[indexNew];
				System.arraycopy(affixed, 0, options, 0, indexNew);
			}
			/*
			 * 若标题无匹配且完美递增，可以视为正常记录直接入库。
			 * 除非在最后一个选项中刚好出现比它大1的标号匹配，构成了完美连续的情况，会被程序增加一个选项，这种几率很小。
			 * 也许可以考虑在完美递增的情况下，再增加一个限制，根据最后一个匹配的标号之前那个字符的类型进行判断，再次缩小这个几率。
			 */
		}
		return options;
	}
	
	public static void main(String args[]) {
		String sourceStr = readToString(new File("C:\\Users\\IAS\\Desktop\\zzx.txt"));
		String[] options = splitOptions(sourceStr);
		System.out.println("\nlength:" + options.length + "\n");
		for (String option : options) {
			System.out.println(option);
		}
	}
	
	/**
	 * 把整个文件一次性读取，以确保能保留原格式
	 */
	public static String readToString(File file) {
		long length = file.length();
		byte[] buffer = new byte[(int) length];
		try {
			FileInputStream in = new FileInputStream(file);
			in.read(buffer);
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		String fileStr = null;
		fileStr = new String(buffer, Charset.forName("GBK"));
		return fileStr;
	}

}
